/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
 * This file is part of JMail                                              *
 * Copyright (C) 2002-2003 Yvan Norsa <norsay@wanadoo.fr>                  *
 *                                                                         *
 * JMail is free software; you can redistribute it and/or modify           *
 * it under the terms of the GNU General Public License as published by    *
 * the Free Software Foundation; either version 2 of the License, or       *
 * any later version.                                                      *
 *                                                                         *
 * JMail is distributed in the hope that it will be useful,                *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of          *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           *
 * GNU General Public License for more details.                            *
 *                                                                         *
 * You should have received a copy of the GNU General Public License along *
 * with JMail; if not, write to the Free Software Foundation, Inc.,        *
 * 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                 *
 *                                                                         *
 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

import java.util.*;
import javax.naming.*;
import javax.naming.directory.*;
import javax.swing.*;

/** Class allowing to interact with the LDAP server */
final class LdapSearch {
	/**
	 * Does a query on the LDAP directory
	 * 
	 * @param url
	 *            LDAP server url
	 * @param base
	 *            base used in the directory
	 * @param login
	 *            LDAP login
	 * @param password
	 *            LDAP password
	 * @param searchLevel
	 *            search scope
	 * @param filter
	 *            name to look for
	 * @param fields
	 *            name of the name and mail fields
	 */
	private static Vector search(String url, String base, String login,
			String password, String searchLevel, String filter, String fields[]) {
		Vector result = new Vector();

		Hashtable env = new Hashtable();
		env.put(Context.INITIAL_CONTEXT_FACTORY,
				"com.sun.jndi.ldap.LdapCtxFactory");
		env.put(Context.PROVIDER_URL, url);

		if (login.compareTo("") != 0 && password.compareTo("") != 0) {
			env.put(Context.SECURITY_PRINCIPAL, login);
			env.put(Context.SECURITY_CREDENTIALS, password);
		}

		try {
			DirContext ctx = new InitialDirContext(env);

			int level;

			if (searchLevel.compareTo("one") == 0)
				level = SearchControls.ONELEVEL_SCOPE;

			else if (searchLevel.compareTo("base") == 0)
				level = SearchControls.OBJECT_SCOPE;

			else if (searchLevel.compareTo("tree") == 0)
				level = SearchControls.SUBTREE_SCOPE;

			SearchControls constraints = new SearchControls();
			constraints.setSearchScope(SearchControls.SUBTREE_SCOPE);

			NamingEnumeration results = ctx.search(base, filter, constraints);

			if (results == null)
				return (null);

			SearchResult aResult;
			Attributes attrs;
			Attribute attr;

			while (results.hasMoreElements()) {
				aResult = (SearchResult) results.nextElement();

				if (fields.length == 0)
					result.add(aResult);

				else {
					attrs = aResult.getAttributes();
					attr = null;

					for (int i = 0; i < fields.length; i++) {
						attr = attrs.get(fields[i]);

						if (attr != null)
							result.add((String) attr.get());
					}
				}
			}
		}

		catch (CommunicationException commE) {
			JOptionPane.showMessageDialog(null, commE.getMessage(),
					"CommunicationException", JOptionPane.ERROR_MESSAGE);
			return (null);
		}

		catch (InvalidNameException invalidE) {
			JOptionPane.showMessageDialog(null, invalidE.getMessage(),
					"InvalidNameException", JOptionPane.ERROR_MESSAGE);
			return (null);
		}

		catch (NameNotFoundException nameE) {
			JOptionPane.showMessageDialog(null, nameE.getMessage(),
					"NameNotFoundException", JOptionPane.ERROR_MESSAGE);
			return (null);
		}

		catch (NamingException e) {
			JOptionPane.showMessageDialog(null, e.getMessage(), e.getClass()
					.getName(), JOptionPane.ERROR_MESSAGE);
			// e.printStackTrace();
			return (null);
		}

		return (result);
	}

	/**
	 * Gets the list of every addresses on the LDAP directory
	 * 
	 * @param profile
	 *            user profile
	 * @return the list of every entries
	 */
	protected final static Vector getList(Profile profile) {
		StringBuffer url = new StringBuffer(profile.getUrl() + ":"
				+ profile.getPort());

		String suffix = profile.getSuffix();

		if (profile.getAddSuffixToURL())
			url.append("/" + suffix);

		StringBuffer base = new StringBuffer(profile.getBase());

		if (profile.getAddSuffixToBase())
			base.append(", " + suffix);

		StringBuffer login = new StringBuffer(profile.getLdapLogin());

		if (profile.getAddSuffixToLogin())
			login.append(", " + suffix);

		String fields[] = new String[2];
		fields[0] = profile.getLdapNameField();
		fields[1] = profile.getLdapMailField();

		Vector res = search(url.toString(), base.toString(), login.toString(),
				profile.getLdapPassword(), "one", profile.getLdapNameField()
						+ "=*", fields);

		if (res == null)
			return (null);

		Vector v = new Vector();

		int size = res.size();

		Entry entry = null;

		for (int i = 0; i < size; i += 2) {
			entry = new Entry((String) res.get(i), (String) res.get(i + 1));
			v.add(entry);
		}

		return (v);
	}

	/**
	 * Adds an entry in the LDAP directory
	 * 
	 * @param profile
	 *            user profile
	 * @param name
	 *            name to add
	 * @param mail
	 *            mail address to add
	 * @param fields
	 *            extra fields
	 * @deprecated Use {@link EditProfile#addEntry(Profile,String,String,String[])} instead
	 */
	protected static final void addEntry(Profile profile, String name,
			String mail, String fields[]) {
				EditProfile.addEntry(profile, name, mail, fields);
			}

	/**
	 * Does a query to the LDAP server to add an entry
	 * 
	 * @param url
	 *            LDAP server url
	 * @param base
	 *            base used in the directory
	 * @param nameField
	 *            name of the "name" field
	 * @param mailField
	 *            name of the "mail" field
	 * @param login
	 *            LDAP login
	 * @param password
	 *            LDAP password
	 * @param entryName
	 *            name of the new entry
	 * @param entryMail
	 *            mail address of the new entry
	 * @param fields
	 *            extra fields
	 */
	static void add(String url, String base, String nameField,
			String mailField, String login, String password, String entryName,
			String entryMail, String fields[]) {
		String principal = login;
		String credentials = password;

		DirContext ctx;

		Hashtable env = new Hashtable();

		env.put(Context.INITIAL_CONTEXT_FACTORY,
				"com.sun.jndi.ldap.LdapCtxFactory");
		env.put(Context.PROVIDER_URL, url);
		env.put(Context.SECURITY_AUTHENTICATION, "simple");
		env.put(Context.SECURITY_PRINCIPAL, principal);
		env.put(Context.SECURITY_CREDENTIALS, credentials);

		try {
			ctx = new InitialDirContext(env);

			Attributes attrs = new BasicAttributes();

			Attribute name = new BasicAttribute(nameField);
			name.add(entryName);

			Attribute mail = new BasicAttribute(mailField);
			mail.add(entryMail);

			attrs.put(mail);
			attrs.put(name);

			int nb = fields.length / 2;

			Attribute at = null;

			for (int i = 0; i < nb; i++) {
				at = new BasicAttribute(fields[i * 2]);
				at.add(fields[(i * 2) + 1]);
				attrs.put(at);
			}

			ctx.bind(nameField + "=" + entryName + ", " + base, null, attrs);

			ctx.close();
		}

		catch (NamingException e) {
			JOptionPane.showMessageDialog(null, e.getMessage(),
					"NamingException", JOptionPane.ERROR_MESSAGE);
		}
	}
}
